<?php

namespace app\api\controller;

use think\cache\driver\Redis;
use Pheanstalk\Pheanstalk;
use think\Exception;
use think\Log;
use think\Request;

// 发送模板消息
class Tempheanstalk extends Base
{

    public $redis;
    public $ser;
    public $headers = array("Content-type: application/json;charset=UTF-8", "Accept: application/json", "Cache-Control: no-cache", "Pragma: no-cache");

    // 初始化操作
    public function __construct(Request $request = null)
    {
        parent::__construct($request);
        $this->ser = new Pheanstalk('127.0.0.1');
        $this->redis = new Redis($options = ['select' => 'sendtmp', 'persistent' => true]);
        set_time_limit(0);
    }

    // 开启监听
    public function start()
    {
        echo 'start';

        while (1) {
            $job = $this->ser->watch('sendtmp')->ignore('default')->reserve(); // 监听管道
            $data = json_decode($job->getData(), true);

            $appid = $data['appid'];
            $tmp = $data['tmp'];

            try {
                $txt = fopen('/www/wwwroot/xcx.nanxuncn.cn/public/openids/' . $appid . '.txt', 'r');
                while (!feof($txt)) {
                    // 拿取openid并发送
                    $this->send_msg(fgets($txt), $tmp);
                }
            } catch (Exception $exception) {
                Log::record($exception);
            }

            $this->ser->delete($job);
            usleep(100);
        }
    }

    // 发送消息
    public function send_msg($openid, $tmp)
    {
        if ($openid) {
            $openid = str_replace(PHP_EOL, '', $openid);
            try {
                $formId = $this->get_formid($openid); // 获取formId
            } catch (Exception $exception) {
                Log::record($exception);
            }
            $token = $this->get_access_token();

            if ($token) {
                $url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' . $token;
                $templateData = $this->create_template($openid, $tmp, $formId);//拼接模板数据
                $res = json_decode($this->http($url, $templateData, 'POST', $this->headers));
                if ($res->errcode == 0) {
                    return true;
                } else {
                    Log::error($openid . ":");
                    Log::error($res);
                    return false;
                }
            } else {
                Log::error('token获取失败');
                return false;
            }
        }
    }

    // 拼装模板，创建通知内容
    private function create_template($openId, $tmp, $formId)
    {
        foreach ($tmp['data'] as $k => $v) {
            $templateData[$k]['value'] = $v['text'];
        }
        $data['emphasis_keyword'] = 'keyword1.DATA';
        $data['touser'] = $openId;
        $data['template_id'] = $tmp['template_id'];
        $data['page'] = $tmp['page'];
        $data['form_id'] = $formId;
        $data['data'] = $templateData;
        return json_encode($data);
    }

    // 取出一个可用的用户openId对应的推送码
    public function get_formid($openId)
    {
        $res = $this->_get($openId);
        if ($res) {
            if (!count($res)) {
                return FALSE;
            }
            $newData = array();
            $result = FALSE;
            for ($i = 0; $i < count($res); $i++) {
                if ($res[$i]['expire'] > time()) {
                    $result = $res[$i]['formId'];//得到一个可用的formId
                    for ($j = $i + 1; $j < count($res); $j++) {//移除本次使用的formId
                        array_push($newData, $res[$j]);//重新获取可用formId组成的新数组
                    }
                    break;
                }
            }
            $this->_save($openId, $newData);
            return $result;
        } else {
            return FALSE;
        }
    }

    // 调用微信api，获取access_token，有效期7200s
    public function get_access_token()
    {
        // 在有效期，直接返回access_token
        if ($this->redis->has('wx38e4080448c98296')) {
            return $this->redis->get('wx38e4080448c98296');
        } else {
            // 不在有效期，重新发送请求，获取access_token
            $url = 'https://api.weixin.qq.com/cgi-bin/token';
            $params['grant_type'] = 'client_credential';
            $params['appid'] = 'wx38e4080448c98296';
            $params['secret'] = '92ab6b63f5d2d1861e5778dc314b105e';

            $result = $this->http($url, $params);
            $res = json_decode($result, true);   //json字符串转数组

            if (array_key_exists('access_token', $res)) {
                $this->redis->set('wx38e4080448c98296', $res['access_token'], 7100);
                return $res['access_token'];
            } else {
                return false;
            }
        }
    }

    // redis get
    private function _get($openid)
    {
        $data = $this->redis->get($openid);
        if ($data) return json_decode($data, TRUE);
        else return FALSE;
    }

    // redis set
    private function _save($openId, $data)
    {
        return $this->redis->set($openId, json_encode($data), 60 * 60 * 24 * 7);
    }

}

$server = new Tempheanstalk();
$server->start();